package com.wondertek.service.service.sys.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.wondertek.common.enums.StatusEnum;
import com.wondertek.common.exception.AppException;
import com.wondertek.service.dto.sys.req.SysRoleAddReq;
import com.wondertek.service.dto.sys.req.SysRoleMenuReq;
import com.wondertek.service.dto.sys.req.SysRoleQueryReq;
import com.wondertek.service.dto.sys.req.SysRoleUpdateReq;
import com.wondertek.service.entity.sys.SysRoleMenuPo;
import com.wondertek.service.entity.sys.SysRolePo;
import com.wondertek.service.entity.sys.SysUserRolePo;
import com.wondertek.service.mapper.sys.SysRoleMapper;
import com.wondertek.service.service.sys.*;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * @author xqs
 */
@Service
@RequiredArgsConstructor
public class SysRoleServiceImpl extends ServiceImpl<SysRoleMapper, SysRolePo> implements ISysRoleService {

    private final ISysRoleMenuService sysRoleMenuService;

    private final ISysUserRoleService sysUserRoleService;

    private final SysRoleMapper sysRoleMapper;

    private final ISysMenuService sysMenuService;

    @Override
    public Page<SysRolePo> page(SysRoleQueryReq sysRoleQueryReq) {
      //  if(true)  throw new AppException(LanguageCodeStatus.ROLE_CODING_DUPLICATION);
        LambdaQueryWrapper<SysRolePo> wrapper = new LambdaQueryWrapper<>();
        if(ObjectUtil.isNotEmpty(sysRoleQueryReq.getRoleName())){
            wrapper.and(i -> i.like(SysRolePo::getRoleName, sysRoleQueryReq.getRoleName()));
//                    .or().like(SysRolePo::getDescription, sysRoleQueryReq.getRoleName()));
        }
        if(ObjectUtil.isNotEmpty(sysRoleQueryReq.getStatus())){
            wrapper.eq(SysRolePo::getStatus,sysRoleQueryReq.getStatus());
        }
        wrapper.orderByDesc(SysRolePo::getCreateTime);
        return this.page(new Page<>(sysRoleQueryReq.getPageNo(), sysRoleQueryReq.getPageSize()), wrapper);
    }

    @Override
    public List<SysRolePo> findList() {
        return this.lambdaQuery().eq(SysRolePo::getStatus, StatusEnum.ENABLE.getCode())
                .orderByDesc(SysRolePo::getCreateTime).list();
    }

    @Override
    public List<SysRolePo> findListByUserId(String userId) {
        return sysRoleMapper.findListByUserId(userId,"");
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void add(SysRoleAddReq sysRoleAddReq) {
        //保存角色
        if(this.lambdaQuery().eq(SysRolePo::getRoleName,sysRoleAddReq.getRoleName()).count()>0){
            throw new AppException("role.name.not.repeat");
        }
        String code = RandomUtil.randomStringUpper(6);
//        if(this.lambdaQuery().eq(SysRolePo::getRoleName,sysRoleAddReq.getRoleCode()).count()>0){
//            throw new AppException("role.code.not.repeat");
//        }
        SysRolePo sysRolePo = new SysRolePo();
        BeanUtil.copyProperties(sysRoleAddReq,sysRolePo);
        String roleId = IdUtil.fastSimpleUUID();
        sysRolePo.setId(roleId);
        sysRolePo.setRoleCode(code);
        this.save(sysRolePo);
        //保存角色权限关联关系
        saveRoleMenu(roleId,sysRoleAddReq.getRoleMenuReqList());
    }

    private void saveRoleMenu(String roleId,List<SysRoleMenuReq> roleMenuReqList){
        Set<SysRoleMenuPo> poleMenuPos = roleMenuReqList.stream().map(menuId -> {
            SysRoleMenuPo sysRoleMenuPo = new SysRoleMenuPo();
            sysRoleMenuPo.setMenuId(menuId.getMenuId());
            sysRoleMenuPo.setType(menuId.getType());
            sysRoleMenuPo.setRoleId(roleId);
            return sysRoleMenuPo;
        }).collect(Collectors.toSet());
        sysRoleMenuService.saveBatch(poleMenuPos);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void update(SysRoleUpdateReq sysRoleUpdateReq) {
        String id = sysRoleUpdateReq.getId();
        //更新角色信息
        SysRolePo sysRolePo = this.getById(id);
        if(sysRolePo==null){
           // throw new AppException(String.format("找不到对应角色信息! id:%s",id));
            throw new AppException("role.not.found");
        }
//        if(this.lambdaQuery().eq(SysRolePo::getRoleName,sysRoleUpdateReq.getRoleName()).count()>1){
//            throw new AppException("role.name.not.repeat");
//        }
        if(!StrUtil.equals(sysRolePo.getRoleName(),sysRoleUpdateReq.getRoleName())){
            long count = this.lambdaQuery().eq(SysRolePo::getRoleName, sysRoleUpdateReq.getRoleName())
                    .count();
            if (count > 0) {
                throw new AppException("role.name.not.repeat");
            }
        }
//        if(this.lambdaQuery().eq(SysRolePo::getRoleName,sysRoleUpdateReq.getRoleCode()).count()>1){
//            throw new AppException("role.code.not.repeat");
//        }
        BeanUtil.copyProperties(sysRoleUpdateReq,sysRolePo);
        sysRolePo.setUpdateBy(null);
        sysRolePo.setUpdateTime(null);
        this.updateById(sysRolePo);
        //取消之前角色关联的权限
        LambdaQueryWrapper<SysRoleMenuPo> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(SysRoleMenuPo::getRoleId,id);
        sysRoleMenuService.getBaseMapper().delete(wrapper);
        //保存角色权限关联关系
        saveRoleMenu(id,sysRoleUpdateReq.getRoleMenuReqList());
        // 更新用户权限
//        List<SysUserRolePo> userIdList = sysUserRoleService.lambdaQuery().eq(SysUserRolePo::getRoleId,id).select(SysUserRolePo::getUserId).list();
//        userIdList.forEach(item -> {
//            sysMenuService.updateUserPermissions(item.getUserId());
//        });
    }

    private void checkBind(String id){
        if(sysUserRoleService.lambdaQuery().eq(SysUserRolePo::getRoleId,id).count()>0){
            throw new AppException("role.user.disable");
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void disable(String id) {
        checkBind(id);
        SysRolePo rolePo = this.getById(id);
        if(ObjectUtil.isNotEmpty(rolePo) && StrUtil.equals("admin", rolePo.getRoleCode())){
            throw new AppException("role.internal.not.operate");
        }
        rolePo.setStatus(StatusEnum.DISABLE.getCode());
        this.updateById(rolePo);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void enable(String id) {
        SysRolePo rolePo = this.getById(id);
        rolePo.setStatus(StatusEnum.ENABLE.getCode());
        this.updateById(rolePo);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void delete(String id) {
        SysRolePo rolePo = this.getById(id);
        if(ObjectUtil.isNotEmpty(rolePo) && (StrUtil.equals("admin", rolePo.getRoleCode()) || StrUtil.equals("installer", rolePo.getRoleCode()))){
            throw new AppException("role.internal.not.operate");
        }
        //取消之前角色关联的权限
        LambdaQueryWrapper<SysRoleMenuPo> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(SysRoleMenuPo::getRoleId,id);
        sysRoleMenuService.getBaseMapper().delete(wrapper);
        //取消之前角色关联的用户
        LambdaQueryWrapper<SysUserRolePo> userWrapper = new LambdaQueryWrapper<>();
        userWrapper.eq(SysUserRolePo::getRoleId,id);
        sysUserRoleService.getBaseMapper().delete(userWrapper);
        // 删除角色
        this.removeById(id);
    }
}
